package com.terrapages.wmsc4j.wms;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.imageio.ImageIO;

import org.apache.log4j.Logger;

import com.terrapages.wmsc4j.bean.BBox;

/**
 * This class is used to connect and get Images from WMS interfaces.
 * To use this class, give it the full Path of the WMS service
 * and an example query (WMSParameters) for it top base other requests from.
 * 
 * @author mvivian
 */
public class WMSService {
	private URL wmsURL;
	private WMSParameters wmsQuery;
	
	private static Logger log = Logger.getLogger(WMSService.class);
	
	/**
	 * <p>Creates a WMS Service instance from which you wish to get images.</p>
	 * 
	 * <p>
	 * EXAMPLE<br>
	 * If a your wms requests look somthing like this...<br>
	 * http://wms.yourdomain.com/maps/wms?blah=bleh&foo=bar&hey=yo<br>
	 * ...then create your WMSService like so...<br><br>
	 * URL wmsURL = new URL("http://wms.yourdomain.com/maps/wms");
	 * WMSParameters wmsQuery = WMSParameters.parseQuery("blah=bleh&foo=bar&hey=yo");
	 * WMSService wmsService = new WMSService( wmsURL, wmsQuery );
	 * </p>
	 * 
	 * @param wmsURL The service URL part of a WMS Request. See example.
	 * @param wmsQuery The query parameters part of a WMS Request. See example.
	 */
	public WMSService(URL wmsURL, WMSParameters wmsQuery) {
		this.wmsURL = wmsURL;
		this.wmsQuery = wmsQuery.clone();
	}
	
	/**
	 * gets the WMS parameters used in the last request sent.
	 * @return WMSParameters
	 */
	public final WMSParameters getWmsQuery() {
		return wmsQuery;
	}
	
	/**
	 * Sets a new set of parameters as a base for requesting images from WMS.
	 * 
	 * @param wmsQuery WMS Parameters to use for requesting images from WMS
	 */
	public final void setWmsQuery(WMSParameters wmsQuery) {
		this.wmsQuery = wmsQuery;
	}
	
	/**
	 * Gets the WMS URL being used to make WMS requests 
	 * 
	 * @return URL of the WMS
	 */
	public final URL getWmsURL() {
		return wmsURL;
	}
	
	/**
	 * Points the WMSService at a new url.
	 * 
	 * @param wmsURL the URL to use for the WMS Service.
	 */
	public final void setWmsURL(URL wmsURL) {
		this.wmsURL = wmsURL;
	}
	
	/**
	 * Using the WMSService Attributes already set up,
	 * this method requests via WMS and returns an image.
	 * 
	 * If there was a problem with any of the attributes or the wms service returned some kind of error.
	 * Then null will be returned and an error log will be made.
	 * 
	 * @param boundingBox The spatial BoundingBox coverage of the image to be requested
	 * @param imageSize The size of the image to be requested in pixels
	 * @return BufferedImage of the requested Image. Null if an error occured.
	 */
	public final BufferedImage getImage(BBox boundingBox, Dimension imageSize)
	{
		//Construct the query String 
		String query = "";
		synchronized (wmsQuery) {
			wmsQuery.setBoundingBox(boundingBox);
			wmsQuery.setImageSize(imageSize);
			query = wmsQuery.toQuery();
		}
		
		//Contruct the URL
		URL url = null;
		try {
			String urlString = wmsURL.toString() + '?' + query;
			log.debug("WMS Request url: " + urlString);
			url = new URL(urlString);
		} catch (MalformedURLException e) {
			log.error("WMS url was invalid", e);
		}
		
		//Get the image
		BufferedImage retImage =null;
		try{
			if(url!=null)
			{
				retImage = ImageIO.read(url);
			}
		} catch (IOException e) {
			log.error("An error occured reading the wms response. It is likely the response was an XML error response and not an image.",e);
		}
		return retImage;
	}
	
}
